package com.csii.pos.activiti.service.impl;

import com.csii.adhoc.exception.ActStartException;
import com.csii.adhoc.exception.ActSubmitException;
import com.csii.adhoc.exception.ParamValidityException;
import com.csii.adhoc.info.user.UserPo;
import com.csii.adhoc.info.user.mapper.UserMapper;
import com.csii.adhoc.info.user.service.UserService;
import com.csii.pos.activiti.mapper.ActivitiScalePlanMapper;
import com.csii.pos.activiti.service.ActivitiScalePlanService;
import com.csii.pos.scaleplan.IfbScalePlan;
import lombok.extern.slf4j.Slf4j;
import org.activiti.engine.ActivitiException;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.apache.shiro.SecurityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @ClassName: ActivitiScalePlanServiceImpl
 * @Author: zhanghao
 * @description: TODO
 * @Date: 2021/7/30 14:36
 * @Version: 1.0
 */
@Service
@Slf4j
public class ActivitiScalePlanServiceImpl implements ActivitiScalePlanService {


    @Autowired
    private RepositoryService repositoryService;

    @Autowired
    private TaskService taskService;

    @Autowired
    private RuntimeService runtimeService;

    @Autowired
    private ActivitiScalePlanMapper activitiScalePlanMapper;
    @Autowired
    private UserMapper userMapper;


    @Override
    public void deploy() {
        repositoryService.createDeployment()
                .name("投融资计划审批流程部署")
                .addClasspathResource("processes/approve_scalePlan.bpmn")
                .addClasspathResource("processes/approve_scalePlan.png")
                .deploy();
    }

    @Override
    @Transactional
    public void startAndSubmit(IfbScalePlan ifbScalePlan) {
        if (StringUtils.isEmpty(ifbScalePlan.getIfbPlanId())) {
            throw new ParamValidityException("投融资计划主键不能为空！");
        }
        //1.获取主键,并拼接为BusinessKey(实体对象名_主键id)
        String BusinessKey = "ifbScalePlan_" + ifbScalePlan.getIfbPlanId();
        String userName = (String) SecurityUtils.getSubject().getPrincipal();
        if (null == userName || "".equals(userName)) {
            throw new RuntimeException("没有获取到当前登录的用户名！");
        }
        //根据主键查询审批状态,若是驳回状态就只提交，否则启动流程并提交
        String approveStatus = activitiScalePlanMapper.getApproveStatus(ifbScalePlan.getIfbPlanId());
//        if (!"4".equals(approveStatus)) {
//            //防止重复提交
//            ProcessInstance planInstance = runtimeService.createProcessInstanceQuery().processDefinitionKey("approve_scalePlan").processInstanceBusinessKey(BusinessKey).singleResult();
//            if (null != planInstance)
//                throw new ActSubmitException("请勿重复提交!");
//            //2.设置当前登录的用户为第一个节点的负责人
//            HashMap<String, Object> varibles = new HashMap<>();
//            varibles.put("user", userName);
//            //3.启动流程
//            try {
//                runtimeService.startProcessInstanceByKey("approve_scalePlan", BusinessKey, varibles);
//            } catch (ActStartException e) {
//                log.error("投融资规模计划启动审批流程失败!");
//                throw new ActStartException("投融资规模计划启动审批流程失败,请删除此数据后重新新增！");
//            }
//        }
//
//        //提交申请
//        //根据流程key、businessKey、当前用户名查询task
//        String taskId = taskService.createTaskQuery().processDefinitionKey("approve_scalePlan").
//                processInstanceBusinessKey(BusinessKey).taskAssignee(userName).singleResult().getId();
//        taskService.complete(taskId);
//        //更新当前数据状态为审批中
//        HashMap<String, Object> map = new HashMap<>();
//        map.put("id", ifbScalePlan.getIfbPlanId());
//        map.put("status", "1");
//        activitiScalePlanMapper.updateStatusById(map);
        //是驳回状态只提交
        if ("4".equals(approveStatus)) {
            //根据流程key、businessKey、当前用户名查询task
            String taskId = taskService.createTaskQuery().processDefinitionKey("approve_scalePlan").
                    processInstanceBusinessKey(BusinessKey).taskAssignee(userName).singleResult().getId();
            taskService.complete(taskId);
            //更新当前数据状态为审批中
            HashMap<String, Object> map = new HashMap<>();
            map.put("id", ifbScalePlan.getIfbPlanId());
            map.put("status", "1");
            activitiScalePlanMapper.updateStatusById(map);
            //驳回后提交,要清空之前审批员的审批意见.
            activitiScalePlanMapper.clearInfo(ifbScalePlan.getIfbPlanId());
        } else {
            //防止重复提交
            ProcessInstance planInstance = runtimeService.createProcessInstanceQuery().processDefinitionKey("approve_scalePlan").processInstanceBusinessKey(BusinessKey).singleResult();
            if (null != planInstance)
                throw new ActSubmitException("请勿重复提交!");
            //2.设置当前登录的用户为第一个节点的负责人
            HashMap<String, Object> varibles = new HashMap<>();
            varibles.put("user", userName);
            //3.启动流程
            try {
                runtimeService.startProcessInstanceByKey("approve_scalePlan", BusinessKey, varibles);
            } catch (ActStartException e) {
                log.error("投融资规模计划启动审批流程失败!");
                throw new ActStartException("投融资规模计划启动审批流程失败,请删除此数据后重新新增！");
            }
            //根据流程key、businessKey、当前用户名查询task
            String taskId = taskService.createTaskQuery().processDefinitionKey("approve_scalePlan").
                    processInstanceBusinessKey(BusinessKey).taskAssignee(userName).singleResult().getId();
            taskService.complete(taskId);
            //更新当前数据状态为审批中
            HashMap<String, Object> map = new HashMap<>();
            map.put("id", ifbScalePlan.getIfbPlanId());
            map.put("status", "1");
            activitiScalePlanMapper.updateStatusById(map);
        }
    }

    @Override
    public void start(IfbScalePlan ifbScalePlan) {
        /*if (StringUtils.isEmpty(ifbScalePlan.getIfbPlanDate())
                || StringUtils.isEmpty(ifbScalePlan.getPrdNmCns())
                || StringUtils.isEmpty(ifbScalePlan.getIfbToolType())){
            throw new ParamValidityException("ifbScalePlan主键字段不能为空!");
        }
        //1.获取主键,并拼接为BusinessKey(实体对象名_主键id)
        String BusinessKey = "ifbScalePlan_" + ifbScalePlan.getIfbPlanDate() + "_"
                + ifbScalePlan.getPrdNmCns() + "_" + ifbScalePlan.getIfbToolType();
        //2.设置当前登录的用户为第一个节点的负责人
        HashMap<String, Object> varibles = new HashMap<>();
        String userName = (String) SecurityUtils.getSubject().getPrincipal();
        varibles.put("user", userName);
        //3.启动流程
        try {
            ProcessInstance instance = runtimeService.startProcessInstanceByKey("approve", BusinessKey, varibles);
        }catch (ActStartException e){
            throw new ActStartException("新增投融资规模计划时启动审批流程失败,请删除此数据后重新新增！");
        }*/
    }

    @Override
    public void submit(List<IfbScalePlan> ifbScalePlanList) {
        if(ifbScalePlanList.size() == 0)
            throw new ParamValidityException("至少选中一条数据！");
        String userName = (String) SecurityUtils.getSubject().getPrincipal();

        //处理批量提交
        for (IfbScalePlan id : ifbScalePlanList){
            if (StringUtils.isEmpty(id)){
                throw new ParamValidityException("主键不能为空!");
            }
            //拼接businessKey(实体对象名_主键id)
            String businessKey = "UofPlanPo_" + id;
            ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceBusinessKey(businessKey).singleResult();
            if (processInstance == null){
                throw new ActStartException("当前资金计划未启动审批流程，请删除后重新新增资金计划！");
            }
            Task task = taskService.createTaskQuery()
                    .processInstanceId(processInstance.getId())
                    .taskAssignee(userName)
                    .singleResult();
            //判断是否任务已提交
            if (task == null)
                throw new ActSubmitException("此资金计划已提交，请核查数据审批状态！");
            //提交申请
            taskService.complete(task.getId());
            //更新当前数据状态为审批中
            HashMap<String, Object> map = new HashMap<>();
            map.put("id", id);
            map.put("status", "1");
            activitiScalePlanMapper.updateStatusById(map);

        }
    }

    @Override
    public void delete(List<IfbScalePlan> ifbScalePlanList) {
        if (ifbScalePlanList.size() == 0)
            throw new ParamValidityException("至少选择一个");
        for (IfbScalePlan id : ifbScalePlanList){
            if (StringUtils.isEmpty(id.getIfbPlanId())){
                throw new ParamValidityException("主键为空!");
            }
            //拼接businessKey(实体对象名_主键id)
            String businessKey = "ifbScalePlan_" + id.getIfbPlanId();
            ProcessInstance instanceSingle =
                    runtimeService.createProcessInstanceQuery().processInstanceBusinessKey(businessKey).singleResult();
            if (instanceSingle == null)
                return;
            runtimeService.deleteProcessInstance(instanceSingle.getId(), "提交人删除申请计划！");
        }
    }

    @Override
    public void agreeByApprover(IfbScalePlan ifbScalePlan) {

        //通过当前记录组装 businessKey,并通过 businessKey获取task.
        String businessKey = "ifbScalePlan_" + ifbScalePlan.getIfbPlanId();
        Task task = taskService.createTaskQuery().processDefinitionKey("approve_scalePlan").processInstanceBusinessKey(businessKey)
                .taskAssignee("审批员").singleResult();
        if (null == task)
            throw new ActSubmitException("在审批流程中未查询到当前数据!");
        //complete当前此任务
        HashMap<String, Object> map = new HashMap<>();
        //查询当前登录的用户名
        String userName = (String) SecurityUtils.getSubject().getPrincipal();
        if (null == userName || "".equals(userName)) {
            throw new RuntimeException("没有获取到当前登录的用户名！");
        }
        //查询中文用户名
        String chUserName = userMapper.selectUserByUserName(userName).getName();
        map.put("status","2");
        taskService.complete(task.getId(), map);
        //如果流程结束则更新数据状态为同意
        Task task1 = taskService.createTaskQuery().processDefinitionKey("approve_scalePlan").processInstanceBusinessKey(businessKey)
                .taskAssignee("审批员").singleResult();
        //更新审批状态、审批人和审批意见
        if (null == task1){
            map.put("approver", chUserName);
            map.put("advice", ifbScalePlan.getAgtrOpnn());
            map.put("id",ifbScalePlan.getIfbPlanId());
            activitiScalePlanMapper.updateStatusById(map);
        }else {
            throw new ActivitiException("审批同意过程异常!");
        }

    }

    @Override
    public void rejectByApprover(IfbScalePlan ifbScalePlan) {
        //通过当前记录组装 businessKey,并通过 businessKey获取task.
        String businessKey = "ifbScalePlan_" + ifbScalePlan.getIfbPlanId();
        Task task = taskService.createTaskQuery().processDefinitionKey("approve_scalePlan").processInstanceBusinessKey(businessKey)
                .taskAssignee("审批员").singleResult();
        if (null == task)
            throw new ActSubmitException("在审批流程中未查询到当前数据!");
        //complete当前此任务
        HashMap<String, Object> map = new HashMap<>();
        map.put("status","3");
        taskService.complete(task.getId(), map);
        //如果流程结束则更新数据状态为拒绝
        Task task1 = taskService.createTaskQuery().processDefinitionKey("approve_scalePlan").processInstanceBusinessKey(businessKey)
                .taskAssignee("审批员").singleResult();
        //查询当前登录的用户名
        String userName = (String) SecurityUtils.getSubject().getPrincipal();
        if (null == userName || "".equals(userName)) {
            throw new RuntimeException("没有获取到当前登录的用户名！");
        }
        //查询中文用户名
        String chUserName = userMapper.selectUserByUserName(userName).getName();
        if (null == task1){
            map.put("approver", chUserName);
            map.put("advice", ifbScalePlan.getAgtrOpnn());
            map.put("id",ifbScalePlan.getIfbPlanId());
            activitiScalePlanMapper.updateStatusById(map);
        }else {
            throw new ActivitiException("审批拒绝过程异常!");
        }
    }

    @Override
    public void refuteByApprover(IfbScalePlan ifbScalePlan) {
        /*//判断当前用户是否有权限做审批,有则进行下边的操作.
        UserPo user = (UserPo) SecurityUtils.getSubject().getPrincipal();
        if (!user.getRole().contains("审批人员权限id")) {
            log.info("当前用户无审批权限!");
            throw new RuntimeException("当前用户无审批权限!");
        }
        //通过当前记录组装 businessKey,并通过 businessKey获取task.
        String businessKey = "UofPlanPo_" + uofPlanPo.getUofItemSn().toString();
        Task task = taskService.createTaskQuery().processInstanceBusinessKey(businessKey).taskAssignee("审批员").singleResult();
        //complete当前此任务
        HashMap<String, Object> map = new HashMap<>();
        map.put("status","4");
        taskService.complete(task.getId(), map);
        //更新数据状态为驳回
        map.put("id",uofPlanPo.getUofItemSn());
        activitiUofPlanMapper.updateStatusById(map);*/

        //通过当前记录组装 businessKey,并通过 businessKey获取task.
        String businessKey = "ifbScalePlan_" + ifbScalePlan.getIfbPlanId();
        Task task = taskService.createTaskQuery().processDefinitionKey("approve_scalePlan").processInstanceBusinessKey(businessKey)
                .taskAssignee("审批员").singleResult();
        if (null == task)
            throw new ActSubmitException("在审批流程中未查询到当前数据!");
        //complete当前此任务
        HashMap<String, Object> map = new HashMap<>();
        String userName = (String)SecurityUtils.getSubject().getPrincipal();
        //查询中文用户名
        String chUserName = userMapper.selectUserByUserName(userName).getName();
        if (null == userName || "".equals(userName)) {
            throw new RuntimeException("没有获取到当前登录的用户名！");
        }
        map.put("status","4");
        taskService.complete(task.getId(), map);
        map.put("id",ifbScalePlan.getIfbPlanId());
        map.put("advice",ifbScalePlan.getAgtrOpnn());
        map.put("approver",chUserName);
        activitiScalePlanMapper.updateStatusById(map);
    }

    @Override
    public List<IfbScalePlan> findAllInfo(Map<String,String> map) {
        List<Task> taskList = taskService.createTaskQuery().processDefinitionKey("approve_scalePlan").taskAssignee("审批员").list();
        List<String> ids = new ArrayList<>();
        //若无任务,则返回空
        if (taskList.size() == 0) {
            List<IfbScalePlan> scalePlanList = new ArrayList<>();
            return scalePlanList;
        }
        //若有任务,则取出各个任务的businessKey的id.
        for (Task task : taskList) {
            String processInstanceId = task.getProcessInstanceId();
            String businessKey = runtimeService.createProcessInstanceQuery().processInstanceId(processInstanceId).singleResult().getBusinessKey();
            //businessKey的格式为scalePlan_id , 遍历截取id
            ids.add(businessKey.split("_")[1]);
        }
        String dateStr = "";
        if (null != map){
            dateStr = map.get("ifbPlanDate");
        }
        List<IfbScalePlan> info = activitiScalePlanMapper.findAllInfo(ids, dateStr);
        return info;
    }


}
